package pers.landriesnidis.easysocket.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;

import pers.landriesnidis.easysocket.server.io.BufferedReader;

public abstract class BaseServerSocketThread extends Thread {

	/**
	 * 数据处理模式
	 * READ_LINE 		按行读取
	 * USE_ADAPTER 		使用数据适配器处理
	 * AUTO 			自动选择(默认)
	 */
	public static enum DATA_RECEPTION_MODE{
		READ_LINE,
		READ_BYTES
	}
	
	//Socket对象
	private final Socket socket;
	//线程结束开关
	private boolean isRun = true;
	//字符编码
	private String encode = "UTF-8";
	//数据接收模式
	private DATA_RECEPTION_MODE receptionMode = DATA_RECEPTION_MODE.READ_LINE;
	//数据接收模式修改标志
	private boolean isReceptionModeChanged = false;
	//以字节数组方式接收数据时数组的单次最大长度
	private int intBytesMaxLength = 2048;
	
	/**
	 * BaseServerSocketThread是抽象类，如果要直接构造，需要立即实现抽象方法
	 * 
	 * @param socket
	 *            用于通信的socket对象
	 */
	public BaseServerSocketThread(Socket socket) {
		this.socket = socket;
		try {
			socket.setKeepAlive(true); 	// 启用心跳检测
			socket.setTcpNoDelay(true); // 禁用nagle算法
		} catch (SocketException e) {

		}
	}

	/**
	 * 结束线程
	 */
	public void close() {
		isRun = false;
		try {
			if (!socket.isClosed()||socket.isConnected())
				socket.close();
		} catch (IOException e) {
		}
		interrupt(); // 结束线程
		onClosed();	
	}

	/**
	 * 接收Socket客户端发来的字符串数据
	 * 
	 * @param strline
	 */
	public abstract void onReceiveData(String strline);
	
	/**
	 * 接收Socket客户端发来的字节数组数据
	 * 
	 * @param strline
	 */
	public abstract void onReceiveData(byte[] arr,int length);

	/**
	 * 成功建立连接
	 */
	public abstract void onConnected();

	/**
	 * 断开连接
	 */
	public abstract void onClosed();

	/**
	 * 发送字符串
	 * 
	 * @param messgae
	 */
	public synchronized void sendString(String messgae) {
		try {
			// 返回此套接字的输出流
			getSocket().getOutputStream().write(
					(messgae + "\n").getBytes(encode));
		} catch (UnsupportedEncodingException e) {
			System.err.println("字符编码设置有误!");
			e.printStackTrace();
			return;
		} catch (IOException e) {
			e.printStackTrace();
			close();
		}
	}

	/**
	 * 发送字节数组
	 * @param bytes
	 */
	public synchronized void send(byte[] bytes) {
		try {
			getSocket().getOutputStream().write(bytes);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {

		onConnected();
		
		try {
			//当[数据接收模式]发生改变时,重新进入模式选择环节
			while(isReceptionModeChanged){
				
				isReceptionModeChanged = false;
				
				//数据接受模式选择
				switch(receptionMode){
				case READ_LINE:
					dataReception_Readline(getSocket().getInputStream());
					break;
				case READ_BYTES:
					dataReception_ReadBytes(getSocket().getInputStream());
					break;
				}
			}
		} catch (IOException e) {
			if(isRun){
				//连接意外中断导致关闭
				e.printStackTrace();
			}else{
				//主动关闭
			}
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
			}
			close();
		}
	}
	
	/**
	 * 数据接收模式：按行读取
	 * 如果设置的数据适配器则使用适配器
	 * @param br
	 * @throws IOException
	 */
	private void dataReception_Readline(InputStream is) throws IOException{
		String line = "";
		BufferedReader br = null;
		
		try {
			br = new BufferedReader(new InputStreamReader(getSocket().getInputStream(), encode),intBytesMaxLength);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		while (((line = br.readLine()) != null) && isRun) {
			onReceiveData(line);
			//返回模式选择环节
			if(isReceptionModeChanged){
				onReceiveData(new String(br.readBufferChars()));
				break;
			}
		}
	}
	
	/**
	 * 数据接收模式：使用字符串适配器
	 * 如果设置的数据适配器则使用适配器
	 * @param br
	 * @throws IOException
	 */
	private void dataReception_ReadBytes(InputStream is) throws IOException{
		byte[] buf = new byte[intBytesMaxLength];
		int length = 0;
		while((length=is.read(buf, 0, intBytesMaxLength))!=-1){
			onReceiveData(buf,length);
			//返回模式选择环节
			if(isReceptionModeChanged)break;
		}
	}
	
	/**
	 * 获取Socket对象
	 * @return
	 */
	public Socket getSocket() {
		return socket;
	}
	
	/**
	 * 获取对方的IP地址
	 * @return
	 */
	public SocketAddress getRemoteSocketAddress(){
		return socket.getRemoteSocketAddress();
	}

	/**
	 * 设置字符编码
	 * @param encode 字符编码名称，默认是"UTF-8"
	 */
	public void setEncode(String encode) {
		this.encode = encode;
	}
	
	/**
	 * 设置数据接收的模式，默认值为DATA_RECEPTION_MODE.READ_LINE（以字符串形式按行读取）
	 * @param receptionMode
	 */
	public void setReceptionMode(DATA_RECEPTION_MODE receptionMode) {
		this.receptionMode = receptionMode;
	}
	
	/**
	 * 获取数据接收的模式
	 * @return
	 */
	public DATA_RECEPTION_MODE getReceptionMode() {
		return receptionMode;
	}
	
	/**
	 * 设置以字符数组方式接收数据时单次接受的数组最大长度，默认值为2048
	 * @param intByteArrayLength
	 */
	public void setBytesMaxLength(int intByteArrayLength) {
		this.intBytesMaxLength = intByteArrayLength;
	}
	
	/**
	 * 获取以字符数组方式接收数据时单次接受的数组最大长度
	 * @return
	 */
	public int getBytesMaxLength() {
		return intBytesMaxLength;
	}
	
}